package com.pine.app.module.security.core.session.impl;

import com.pine.app.module.security.core.Authentication;
import com.pine.app.module.security.core.session.AuthenticationSessionStore;
import com.pine.app.module.security.oauth.provider.SsoOAuth2Authentication;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @author xiaoyuan
 * @create 2020/3/17 17:13
 **/
public class AuthenticationSessionStoreImpl implements AuthenticationSessionStore {
    private boolean migrateSessionAttributes = true;
    private static final String AUTHENTICATION_SESSION_KEY = "PINE_SECURITY_AUTHENTICATION";

    @Override
    public void saveAuthtication(HttpServletRequest request, Authentication authentication) {
        HttpSession httpSession = request.getSession(false);
        Map<String, Object> attributesToMigrate = null;
        if (httpSession != null) {
            attributesToMigrate = this.createMigratedAttributeMap(httpSession);
            httpSession.invalidate();
        }
        httpSession = request.getSession(true);
        if (attributesToMigrate != null) {
            transferAttributes(attributesToMigrate, httpSession);
        }
        httpSession.setAttribute(AUTHENTICATION_SESSION_KEY, authentication);
    }

    @Override
    public Authentication loadAuthentication(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session == null) {
            return null;
        }
        Object object = session.getAttribute(AUTHENTICATION_SESSION_KEY);
        if (object == null) {
            return null;
        }
        if (object instanceof Authentication) {
            Authentication authentication = (Authentication) object;
            if(authentication instanceof SsoOAuth2Authentication){
                SsoOAuth2Authentication ssoOAuth2Authentication     = (SsoOAuth2Authentication) authentication;
                //如果是单点登陆   那么校验token的过期时间
                if(ssoOAuth2Authentication.getAuth2AccessToken().getExpiresIn()<=0){
                    return null;
                }
            }
            return (Authentication) object;
        }
        return null;
    }

    @Override
    public void removeAuthtication(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.removeAttribute(AUTHENTICATION_SESSION_KEY);
        }
    }

    private void transferAttributes(Map<String, Object> attributes, HttpSession newSession) {
        if (attributes != null) {
            Iterator var3 = attributes.entrySet().iterator();

            while (var3.hasNext()) {
                Map.Entry<String, Object> entry = (Map.Entry) var3.next();
                newSession.setAttribute(entry.getKey(), entry.getValue());
            }
        }

    }

    private HashMap<String, Object> createMigratedAttributeMap(HttpSession session) {
        HashMap<String, Object> attributesToMigrate = new HashMap();
        Enumeration enumer = session.getAttributeNames();
        while (true) {
            String key;
            do {
                if (!enumer.hasMoreElements()) {
                    return attributesToMigrate;
                }
                key = (String) enumer.nextElement();
            } while (!this.migrateSessionAttributes && !key.startsWith("PINE_SECURITY_"));

            attributesToMigrate.put(key, session.getAttribute(key));
        }
    }
}
